/*
 * mailcmd.h
 *
 *  Created on: 14/lug/2014
 *      Author: root
 */

#ifndef CMD_H_
#define CMD_H_

#include <time.h>

#include "arpamessage.h"
#include "smtp_pop3.h"
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "config.h"


#define MIN25 (25*60)
#define REG_LIST 2677
#define LOCAL_DOMAIN "pikappa.it"
#define LOCAL_IP_ADDRESS "127.0.0.1"
#define MSG_MAILDAEM_HEAD "Delivery to the following recipient failed permanently: \r\n"
#define MSG_MAILDAEM_BODY "The error that the other server returned was: \r\n"
#define MSG_MAILDAEM_ORIG_MSG "\r\n\r\n----- Original message -----\r\n"

#define MAX_RSP 5
#define MAX_RSP_PAR 10

int regId;
int regSemId;
extern char * secretsFile;
extern int secretsFileSize;
//static const char secretsFile[] = "secrets.csv";
typedef enum MAILSTATE_SMTP{NO_SESSION, MAIL_RCVD, RCPT_RCVD, SESSION_ENDED} SMTP_MAIL_STATE;
typedef enum AUTHSTATE_POP3{NO_STATE, USER_RCVD, PASS_RCVD, AUTHORIZED} POP3_AUTH_STATE;
typedef enum SESSION_TYPE{POP3, SMTP}STYPE;
typedef enum MAIL_TYPE{INCOMING, OUTCOMING}MTYPE;

typedef struct mail{
	char * sender;
	char ** receiversTo;
	/*o state assume i segeuenti valori . stato della sessione per il comando mail RCPT  e DATA
	 * -1 -- nessuna sessione
	 *  0 -- sessione MAIL correttamente iniziata
	 *  1 -- ricevuto correttamente almeno un RCPT dopo MAIL
	 *  2 -- ricevuto correttamente DATA dopo almeno un RCPT
	 * */
	SMTP_MAIL_STATE state;
	/*Parametri del comando corrente*/
	char * data;
	/*0 se la mail viene inviata da
	 * un utente del server, 1 se la mail è in ricezione*/
	MTYPE mailType;
}MAILCMD;

typedef MAILCMD * PMAIL;

typedef struct smtpsession{
	/*Comando corrente o smtp o pop3*/
	char *clienthostname;//smtp
	PMAIL mailobject;//smtp
}SMTP_SESSION;

typedef struct pop3session{
	char *user;//pop3
	char *pass;//pop3
	char *msgID;//per LIST, DELE, RETR -- pop3
	ARPAMSG msgList;//File mbox in struttura del file lockato dall sessione corrente -- pop3
	POP3_AUTH_STATE authState; //pop3
	void *mboxfd; // pop3
}POP3_SESSION;

union PROTOCOL{
	SMTP_SESSION smtp;
	POP3_SESSION pop3;
};
typedef union PROTOCOL * PROTOCOL_PTR;

struct session{
	/*Comando corrente o smtp o pop3*/
	CMD cmd;
	char *serv_ip_address;//entrambi
	char *ip_address;//entrambi
	RESPONSE response[MAX_RSP];//entrambi
	time_t lastAccessTime;// entrambi
	STYPE type; //entrambi
	union PROTOCOL protocol;
	char *rspParams[MAX_RSP_PAR]; //entrambi
};
typedef struct session * PTRSESSION;


void parseCmd(char [], PTRSESSION, unsigned int *);
CMD decodeCmd (char * ,STYPE);

void executeCmd(PTRSESSION,struct sockaddr_in *, int, struct sockaddr_in *, CNF_PTR);
void executeHelo(PTRSESSION);
void executeMail(PTRSESSION, struct sockaddr_in * clientSockAddr);
void executeRcpt(PTRSESSION);
void executeData(PTRSESSION, CNF_PTR);

void executePass(PTRSESSION, struct sockaddr_in *, struct flock *, char *);
void executeList(PTRSESSION);
void executeRetr(PTRSESSION);
void executeDele(PTRSESSION);
void executeQuit(PTRSESSION, struct flock *);
void executeRset(PTRSESSION);

int parseHelo(char *, PTRSESSION);
int parseMail(char *, PTRSESSION);
int parseRcpt(char *, PTRSESSION);
void parseData(PTRSESSION, unsigned int *);
int parseUser(char *, PTRSESSION);
int parsePass(char *, PTRSESSION);
int parseList(char *, PTRSESSION);
int parseRetr(char *, PTRSESSION);
int parseDele(char *, PTRSESSION);


char *generateResponse(RESPONSE[], char**, STYPE);
char * decodeRespCode(RESPONSE, int *, int *);
void startSmtpListener(CNF_PTR,unsigned int *, unsigned int *, struct sockaddr_in *);
void startPop3Listener(CNF_PTR,unsigned int *, unsigned int *, struct sockaddr_in *);
void manageSession(unsigned int *, struct sockaddr_in *, struct sockaddr_in *, STYPE, CNF_PTR);
void initSession(PTRSESSION,struct sockaddr_in *, struct sockaddr_in *, unsigned int *, STYPE);
PMAIL initMailObject(PMAIL);

char * readInput(char *, unsigned int *, PTRSESSION);
char * readData(char *, unsigned int *, PTRSESSION);
int receiversByteSize(PTRSESSION);
void writeMailToBox(char *,PTRSESSION, char *);
char * buildMessage(PTRSESSION, int *, char *);
char * buildMessageID(PTRSESSION, int *, char *);
int isProtocolError(PTRSESSION);

int addResponse(RESPONSE[], RESPONSE);
int clearResponse(RESPONSE[]);
int isInResponse(RESPONSE[], RESPONSE);
int addRspParam(char **, char *);
int clearRspParam(char **);

//void mailerDaemonSend(PTRSESSION, CNF_PTR);


//void initPOP3Register(void);
//void addPOP3Register(PREGEL);
//int isRegElemPresent(char *, char *);

//typedef struct registerElem{
//	char * IP_ADDRESS;
//	char * user;
//	int  shmIdnext;
//	int shmId;
//}REGISTERELEM;
//
//typedef REGISTERELEM * PREGEL;

#endif /* MAILCMD_H_ */

